Skip to content

Migrate to generated TypeScript client from ros2_medkit_clients#53

Merged
bburda merged 25 commits intomainfrom
feat/generated-client-migration
Apr 2, 2026
Merged

Migrate to generated TypeScript client from ros2_medkit_clients#53
bburda merged 25 commits intomainfrom
feat/generated-client-migration

Conversation

@bburda
Copy link
Copy Markdown
Contributor

@bburda bburda commented Mar 22, 2026

Pull Request

Summary

Replace the hand-maintained REST client (sovd-api.ts, ~2087 lines) with the generated TypeScript client from @selfpatch/ros2-medkit-client-ts. The Zustand store absorbs all API translation via dispatch helpers and response transforms, keeping the component layer's public interface unchanged.

Key changes:

  • Deleted sovd-api.ts (2087 lines) and its tests
  • Created api-dispatch.ts (524 lines) - entity-type routing for openapi-fetch typed paths
  • Created transforms.ts (362 lines) - response reshaping (field renames, x-medkit extraction)
  • Modified store.ts - swapped SovdApiClient for MedkitClient, migrated SSE fault streaming to SseStream async iterable
  • Updated 14 components - replaced direct client usage with store actions
  • Net result: -636 lines across 33 files

Issue


Type

  • Bug fix
  • New feature
  • Breaking change
  • Documentation only

Testing

  • All 107 tests pass (npm test)
  • TypeScript strict mode passes (npm run typecheck)
  • ESLint passes (npm run lint)
  • Manual verification pending (requires running gateway)

Checklist

  • Breaking changes are clearly described (and announced in docs / changelog if needed)
  • Linting passes (npm run lint)
  • Build succeeds (npm run build)
  • Docs were updated if behavior or public API changed

Copilot AI review requested due to automatic review settings March 22, 2026 21:30
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Migrates the UI from the hand-maintained SovdApiClient to the generated @selfpatch/ros2-medkit-client-ts client, centralizing API path routing and response-shape normalization in the store layer to keep component interfaces stable.

Changes:

  • Replaced the custom REST client with a generated OpenAPI client and added typed dispatch helpers (api-dispatch.ts) for entity-type routing.
  • Introduced pure response mappers (transforms.ts) and corresponding unit tests to reshape gateway responses into UI-friendly types.
  • Updated the Zustand store and multiple components to use store actions instead of direct client calls; removed the old client implementation/tests.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/lib/utils.ts Adds shared helpers (fault entity type mapping, byte/duration formatting) previously living in the old client.
src/lib/utils.test.ts Adds unit coverage for new utility helpers.
src/lib/types.ts Re-exports select generated-client schema types and keeps manual UI types.
src/lib/transforms.ts Adds response transformation utilities extracted from the old client logic.
src/lib/transforms.test.ts Adds unit tests validating the new transformation behaviors.
src/lib/api-dispatch.ts Adds per-entity-type OpenAPI path dispatch wrappers (apps/components/areas/functions).
src/lib/store.ts Switches to generated client, wires dispatch/transforms, updates fault streaming, and adds component-facing store actions.
src/lib/sovd-api.ts Removes the legacy hand-maintained REST client implementation.
src/lib/sovd-api.test.ts Removes tests for the legacy REST client.
src/components/TopicPublishForm.tsx Switches topic publishing to store action instead of direct client usage.
src/components/DataPanel.tsx Removes client prop dependency and delegates publish behavior to store actions.
src/components/EntityDetailPanel.tsx Updates resource-count and data-loading flow to use store actions.
src/components/EntityResourceTabs.tsx Migrates per-tab resource loads to store actions and store-backed configuration state.
src/components/AppsPanel.tsx Replaces direct client calls with store actions for app resources.
src/components/FunctionsPanel.tsx Replaces direct client calls with store actions for function resources and config counts.
src/components/FaultsPanel.tsx Migrates faults list/detail/clear behaviors to store actions and shared utils mapper.
src/components/FaultsDashboard.tsx Migrates fault detail loading to store action and shared utils mapper.
src/components/RosbagDownloadButton.tsx Switches downloads to store action and moves formatting helpers to utils.
src/components/SnapshotCard.tsx Moves formatting helper imports from old client to utils.
src/components/OperationsPanel.tsx Updates SovdResourceEntityType import location post-migration.
src/components/ConfigurationPanel.tsx Updates SovdResourceEntityType import location post-migration.
src/components/ServerInfoPanel.tsx Switches server info fetches to store actions instead of direct client calls.
package.json Adds generated client dependency (and OpenAPI fetch dependency).
.npmrc Configures scoped registry for @selfpatch packages.

@bburda bburda requested a review from mfaferek93 March 23, 2026 15:19
bburda added 10 commits March 23, 2026 16:20
Add generated TypeScript client and openapi-fetch peer dependency.
Configure .npmrc for GitHub Packages registry.
Create standalone transform functions for fault, operations, data,
configurations, and bulk data responses. These handle x-medkit vendor
extension extraction and field renaming.
Move formatBytes, formatDuration, and mapFaultEntityTypeToResourceType
to utils.ts in preparation for sovd-api.ts removal.
Add import of components schema from @selfpatch/ros2-medkit-client-ts.
Re-export VersionInfo and GenericError (as SovdError) from generated
schema where shapes match. Other types stay manual due to significant
API differences - transforms.ts handles runtime mapping.
Route generic (entityType, entityId) calls to the correct per-entity
typed API paths required by openapi-fetch. Covers configurations,
data, operations, executions, faults, and bulk data.
Replace all SovdApiClient method calls with typed openapi-fetch
GET/POST/PUT/DELETE calls via api-dispatch helpers. Migrate SSE
fault streaming from EventSource to SseStream async iterable.
Remove baseEndpoint from AppState (URL normalization is automatic).
Add fetchEntityData, fetchEntityOperations, listEntityFaults,
getFaultWithEnvironmentData, publishToEntityData, getServerCapabilities,
getVersionInfoAction, downloadBulkData, getFunctionHosts, and
prefetchResourceCounts actions.
…th store actions

Migrate 14 components from direct SovdApiClient usage to store actions:
- Group 1 (import-only): SnapshotCard, ConfigurationPanel, OperationsPanel
- Group 2 (import + client replacement): RosbagDownloadButton, FaultsPanel,
  FaultsDashboard, EntityResourceTabs, AppsPanel, FunctionsPanel, ServerInfoPanel
- Group 3 (remove client prop chain): DataPanel, TopicPublishForm, EntityDetailPanel

All imports updated from @/lib/sovd-api to @/lib/types or @/lib/utils.
All direct client.method() calls replaced with store actions.
Updated RosbagDownloadButton test to mock store action instead of client.
Delete sovd-api.ts (~2087 lines) and its tests. All API calls now
go through the generated @selfpatch/ros2-medkit-client-ts client
via the Zustand store and api-dispatch helpers.
- App.tsx: remove baseEndpoint from store selector and connect() call
- ServerConnectionDialog.tsx: remove base endpoint input field entirely
  (generated client normalizes URLs automatically)
- store.ts: remove unused dynamic import, use store serverUrl instead
  of fragile type cast for download URL construction
@bburda bburda force-pushed the feat/generated-client-migration branch from e1007d4 to c7f8997 Compare March 23, 2026 15:22
bburda added 6 commits March 23, 2026 16:32
The publish UI was showing even when disconnected because the
client null check was dropped during migration. Replaced with
isConnected store check.
…lback fetch

- refreshSelectedEntity: use selectedEntity.type/id instead of path parsing
- handleTopicSelection: find parent entity from tree, fetch via getEntityDataItem
- fetchEntityFromApi: use depth heuristic instead of treating path[0] as entityType
- downloadBulkData: add encodeURIComponent for path segments
- Replace all dynamic imports with static imports
- Add entity type field to raw API responses (areas, components, apps)
- Fix topic detail: transform raw DataItem to ComponentTopic for schema
- Fix SSE fault stream: pass fetch.bind(globalThis) to createMedkitClient
- Fix fetchEntityFromApi: parse /data/ and /operations/ resource paths
- Fix snapshot duplicate React keys in FaultsDashboard and FaultsPanel
- Fix getFaultWithEnvironmentData: single request, no brute-force fallback
- Remove console.log info lines, add console.error on all error paths
- Rename browser tab to ros2_medkit Web UI
- Remove all dynamic imports, use static imports only
- ServerConnectionDialog: title and description
- EmptyState: connection prompt text
- ServerInfoPanel: fallback server name
- store.ts: fallback in loadRootEntities
- Fix auto-connect loop in React strict mode
- Add @testing-library/dom to fix peer dep resolution
Prevents UI from getting stuck in 'Connecting...' state when server
doesn't respond. Shows timeout error message and re-enables input.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 33 changed files in this pull request and generated 6 comments.

bburda added 5 commits March 31, 2026 14:50
Remove .npmrc GitHub Packages config - package is now published
to npmjs.com (public, no auth required for install).
Add .serena/ to .gitignore - tool config should not be committed.
Run prettier on all files that failed CI formatting check.
- Fix || to ?? in transformFaultsResponse count (zero treated as falsy)
- Remove debug console.warn from fetchEntityData
- Add error handling to publishToEntityData (try/catch + toast)
- Fix SSE stream error recovery: clear faultStreamCleanup so polling
  fallback can activate instead of silent data staleness
- Fix entity type pluralization: use mapping instead of naive 's' append
- Fix downloadBulkData: use normalizeBaseUrl, add AbortController timeout
- Fix EntityResourceTabs: use ref for loadedTabs to prevent unnecessary
  useCallback/useEffect re-runs
api-dispatch.test.ts: covers all 19 dispatch functions across all
4 entity types, verifying correct path routing and parameter mapping.

store-helpers.test.ts: covers pure helper functions (toTreeNode,
updateNodeInTree, findNode, inferEntityTypeFromDepth, parseTreePath)
with edge cases. Exports 5 previously-private helpers for testability.

Total test count: 107 -> 243
bburda added 2 commits March 31, 2026 22:52
When the gateway returns no areas (empty list), load components
directly under the server node instead of showing an empty tree.

Hierarchy with areas: Server -> Areas -> Components -> Apps
Hierarchy without:    Server -> Components -> Apps
Components can have both subcomponents and apps (hosts) as children.
For example, a hypervisor component may host guest OS subcomponents
and also run its own monitoring apps directly.

loadChildren now fetches subcomponents and hosts in parallel via
Promise.all, showing subcomponents first then apps in the tree.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 33 changed files in this pull request and generated 7 comments.

- Fix SSE faultData null guard: check typeof before 'in' operator
- Move cleanup() declaration before consume() to prevent ReferenceError
- Use || -> ?? for fault payload extraction
- Fix timestamp overflow: Date.now() * 1_000_000 exceeds MAX_SAFE_INTEGER
- Fix handleTopicSelection: transform raw API response through
  transformDataResponse instead of raw cast to ComponentTopic
- Move @testing-library/dom from dependencies to devDependencies
@bburda bburda self-assigned this Apr 2, 2026
Copy link
Copy Markdown

@mfaferek93 mfaferek93 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few comments

… guards

- Eliminate duplicate getEntityData call: prefetchResourceCounts no
  longer fetches data count, EntityDetailPanel uses fetchEntityData
  result length instead
- Extract entity_type from raw fault data when available, fall back
  to 'app' (gateway doesn't include entity_type yet)
- Add runtime guards to all 6 transform functions: return safe
  defaults for null/undefined/non-object input instead of crashing
@mfaferek93 mfaferek93 self-requested a review April 2, 2026 13:20
@bburda bburda merged commit 3af00be into main Apr 2, 2026
3 checks passed
@bburda bburda deleted the feat/generated-client-migration branch April 2, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate to generated TypeScript client from ros2_medkit_clients

3 participants